package com.huilian.iotbox.admin.wap.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huilian.iotbox.admin.wap.dao.DeviceAnnualFeeRecordDao;
import com.huilian.iotbox.admin.wap.service.DeviceAnnualFeeRecordItemService;
import com.huilian.iotbox.admin.wap.service.DeviceAnnualFeeRecordService;
import com.huilian.iotbox.admin.wap.service.DeviceAnnualFeeService;
import com.huilian.iotbox.data.config.AgencyConfig;
import com.huilian.iotbox.data.config.MiddlewareConfig;
import com.huilian.iotbox.data.controller.ControllerException;
import com.huilian.iotbox.data.dto.DeviceAnnualFeeDto;
import com.huilian.iotbox.data.dto.DeviceAnnualFeeRecordDto;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.exception.SysException;
import com.huilian.iotbox.data.po.DeviceAnnualFee;
import com.huilian.iotbox.data.po.DeviceAnnualFeeRecord;
import com.huilian.iotbox.data.po.DeviceAnnualFeeRecordItem;
import com.huilian.iotbox.data.po.SystemMerchantConfig;
import com.huilian.iotbox.data.properties.ConfigProperties;
import com.huilian.iotbox.data.service.SystemMerchantConfigSerivce;
import com.huilian.iotbox.data.utils.*;
import com.huilian.iotbox.data.vo.DeviceAnnualFeeRecordItemVo;
import com.huilian.iotbox.data.vo.DeviceAnnualFeeRecordVo;
import com.huilian.iotbox.data.vo.DeviceAnnualFeeVo;
import com.huilian.tool.common.config.AppletWeChatConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: loong
 * @create: 2024-06-25 17:52
 **/
@Service
@Slf4j
public class DeviceAnnualFeeRecordServiceImpl implements DeviceAnnualFeeRecordService {
    @Resource
    private DeviceAnnualFeeRecordDao deviceAnnualFeeRecordDao;
    @Resource
    private DeviceAnnualFeeService deviceAnnualFeeService;
    @Resource
    private SystemMerchantConfigSerivce systemMerchantConfigSerivce;
    @Resource
    private DeviceAnnualFeeRecordItemService deviceAnnualFeeRecordItemService;
    @Resource
    private AppletWeChatConfig appletWeChatConfig;
    @Resource
    private AgencyConfig agencyConfig;
    @Resource
    private ConfigProperties configProperties;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject pay(DeviceAnnualFeeRecordDto deviceAnnualFeeRecordDto) throws Exception {
        List<DeviceAnnualFeeVo> deviceAnnualFeeVoList = deviceAnnualFeeService.findByIdList(deviceAnnualFeeRecordDto.getIdList());

        BigDecimal totalMoney = BigDecimal.ZERO;
        for (DeviceAnnualFeeVo deviceAnnualFeeVo : deviceAnnualFeeVoList) {
            totalMoney = totalMoney.add(deviceAnnualFeeVo.getUnitPrice());
        }

        SystemMerchantConfig systemMerchantConfig = systemMerchantConfigSerivce.findSystemMerchant();
        if (ObjectUtils.isEmpty(systemMerchantConfig)) {
            throw new Exception("未找到使用中的商户");
        }

        DeviceAnnualFeeRecord deviceAnnualFeeRecord = new DeviceAnnualFeeRecord();
        deviceAnnualFeeRecord.setUserId(deviceAnnualFeeRecordDto.getUserInfo().getId());
        deviceAnnualFeeRecord.setOutTradeNo(Util.getOutTradeNo());
        deviceAnnualFeeRecord.setMerchantId(systemMerchantConfig.getMerchantId());
        deviceAnnualFeeRecord.setTotalAmount(totalMoney);
        deviceAnnualFeeRecord.setPaymentType(DeviceAnnualFeeRecordPaymentTypeEnum.PAY.getCode());

        BigDecimal mFeeVal = systemMerchantConfig.getFeeValue();
        BigDecimal handlingCharge = SciCalUtils.sciCalToBD(mFeeVal.multiply(totalMoney).doubleValue(), 2);
        deviceAnnualFeeRecord.setHandlingCharge(handlingCharge);
        deviceAnnualFeeRecord.setSettlementMoney(totalMoney.subtract(handlingCharge));
        deviceAnnualFeeRecord.setStatus(DeviceAnnualFeeRecordStatusEnum.WAIT.getCode());
        deviceAnnualFeeRecordDao.add(deviceAnnualFeeRecord);

        for (DeviceAnnualFeeVo deviceAnnualFeeVo : deviceAnnualFeeVoList) {
            DeviceAnnualFeeRecordItem deviceAnnualFeeRecordItem = new DeviceAnnualFeeRecordItem();
            deviceAnnualFeeRecordItem.setDeviceAnnualFeeRecordId(deviceAnnualFeeRecord.getId());
            deviceAnnualFeeRecordItem.setDeviceId(deviceAnnualFeeVo.getDeviceId());
            deviceAnnualFeeRecordItem.setAmount(deviceAnnualFeeVo.getUnitPrice());
            deviceAnnualFeeRecordItem.setQuantity(1);
            deviceAnnualFeeRecordItemService.add(deviceAnnualFeeRecordItem);
        }

        Map<String, Object> form = new HashMap<>();
        form.put("outTradeNo", deviceAnnualFeeRecord.getOutTradeNo());
        form.put("body", "设备流量卡续费");
        form.put("totalAmount", totalMoney.multiply(new BigDecimal("100")).intValue());
        form.put("hlMerchantId", deviceAnnualFeeRecord.getMerchantId());
        form.put("channelType", "WX");
        form.put("openId", deviceAnnualFeeRecordDto.getUserInfo().getOpenId());
        form.put("payType", "AppPayApplet");
        form.put("wxAppId", appletWeChatConfig.getAppId());
        form.put("notifyUrl", configProperties.getWapBackEndUrl() + "/api/deviceAnnualFeeRecord/payNotice");
        log.info("参数JSON{}", form);
        String param = HttpUtils.format(agencyConfig, form, FunctionEnum.JS_PAY);
        String response = HttpsMain.httpsReq(MiddlewareConfig.reqUrl + "/pay", param);
        log.info("请求响应结果{}", response);
        //延签并返回map值
        final Map<String, Object> result = HttpUtils.getResultData(response);
        final String status = (String) result.get("status");
        final String code = (String) result.get("code");
        if (status.equals(RequestStatus.SUCCESS.getCode()) && code.equals(RequestStatus.SUCCESS_CODE.getCode())) {
            Object data = result.get("data");
            JSONObject dataJsonObject = JSON.parseObject(data.toString());
            return dataJsonObject.getJSONObject("payInfo");
        } else {
            String msg = (String) result.get("msg");
            if (msg.indexOf("当前服务商因存在违规") != -1) {
                throw new SysException("当前商家暂不支持支付宝支付，请使用微信扫码支付");
            } else if (msg.indexOf("微信认证") != -1) {
                throw new SysException("请商家完成微信认证");
            } else if (msg.indexOf("支付宝认证") != -1) {
                throw new SysException("请商家完成支付宝认证");
            } else {
                throw new SysException((String) result.get("msg"));
            }
        }
    }

    @Override
    public String payNotice(HttpServletRequest request) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String tempLine = "";
        StringBuffer resultBuffer = new StringBuffer();
        while ((tempLine = reader.readLine()) != null) {
            resultBuffer.append(tempLine).append(System.getProperty("line.separator"));
        }
        String response = resultBuffer.toString();
        log.info("支付回调通知报文{}", response);
        final Map<String, Object> res = HttpUtils.getResultData(response);
        Map<String, String> result = (Map<String, String>) res.get("data");
        String outTradeNo = result.get("outTradeNo");
        String totalAmount = result.get("totalAmount");
        if (StringUtils.isEmpty(outTradeNo) || StringUtils.isEmpty(totalAmount)) {
            throw new ControllerException("返回参数有误!");
        }
        DeviceAnnualFeeRecordDto deviceAnnualFeeRecordDto = new DeviceAnnualFeeRecordDto();
        deviceAnnualFeeRecordDto.setOutTradeNo(outTradeNo);
        deviceAnnualFeeRecordDto.setTotalAmount(new BigDecimal(totalAmount).divide(new BigDecimal("100")));
        DeviceAnnualFeeRecordVo deviceAnnualFeeRecordVo = deviceAnnualFeeRecordDao.findByOutTradeNoAndTotalAmount(deviceAnnualFeeRecordDto);

        if (ObjectUtils.isEmpty(deviceAnnualFeeRecordVo)) {
            throw new Exception("未找到对应的订单");
        }

        if (OrderStatusEnum.SUCCESS.getCode().equals(deviceAnnualFeeRecordVo.getStatus())) {
            log.info("流量卡续费订单:" + outTradeNo + "已完成");
            return "SUCCESS";
        }

        DeviceAnnualFeeRecord updateDeviceAnnualFeeRecord = new DeviceAnnualFeeRecord();
        updateDeviceAnnualFeeRecord.setId(deviceAnnualFeeRecordVo.getId());
        updateDeviceAnnualFeeRecord.setStatus(DeviceAnnualFeeRecordStatusEnum.SUCCESS.getCode());
        updateDeviceAnnualFeeRecord.setPayChannelOrderNo(result.get("payChannelOrderNo"));
        updateDeviceAnnualFeeRecord.setMerchantOrderNo(result.get("merchantOrderNo"));
        updateDeviceAnnualFeeRecord.setOrderNo(result.get("orderNo"));

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        updateDeviceAnnualFeeRecord.setGmtPayment(df.parse(result.get("gmtPayment")));
        deviceAnnualFeeRecordDao.update(updateDeviceAnnualFeeRecord);

        List<DeviceAnnualFeeVo> deviceAnnualFeeVoList = deviceAnnualFeeService.findByDeviceAnnualFeeRecordId(deviceAnnualFeeRecordVo.getId());
        for (DeviceAnnualFeeVo deviceAnnualFeeVo : deviceAnnualFeeVoList) {
            DeviceAnnualFee deviceAnnualFee = new DeviceAnnualFeeDto();
            deviceAnnualFee.setId(deviceAnnualFeeVo.getId());
            if (deviceAnnualFeeVo.getDefaultMode() == 1) {
                deviceAnnualFee.setDueDate(DateTimeUtils.plusYearsDate(deviceAnnualFeeVo.getDueDate(), 1));
            } else {
                deviceAnnualFee.setDueDate(DateTimeUtils.plusMonthsDate(deviceAnnualFeeVo.getDueDate(), 1));
            }
            deviceAnnualFeeService.update(deviceAnnualFee);
        }

        return "SUCCESS";
    }

    @Override
    public PageInfo<DeviceAnnualFeeRecordVo> findList(DeviceAnnualFeeRecordDto deviceAnnualFeeRecordDto) {
        PageHelper.startPage(deviceAnnualFeeRecordDto.getPageNum(), deviceAnnualFeeRecordDto.getPageSize());
        List<DeviceAnnualFeeRecordVo> list = deviceAnnualFeeRecordDao.findList(deviceAnnualFeeRecordDto);
        list.forEach(data -> {
            List<DeviceAnnualFeeRecordItemVo> deviceAnnualFeeRecordItemVoList = deviceAnnualFeeRecordItemService.findByDeviceAnnualFeeRecordId(data.getId());
            data.setDeviceAnnualFeeRecordItemVoList(deviceAnnualFeeRecordItemVoList);
        });
        return new PageInfo<>(list);
    }
}
